import React, { useEffect, useState } from 'react';
import {
  AutoComplete,
  Button,
  Cascader,
  Col,
  Form,
  Input,
  message,
  Modal,
  Row,
  Space,
  Switch,
  Tag,
} from 'antd';
import { Select } from 'antd/es';
import { Store } from 'rc-field-form/lib/interface';
import { fetchWorkerZones } from '@/services/testplatform';
import { WorkerZone } from '@/models/testplatform/types';
import { fetchCollections } from '@/services/httptest';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons/lib';
import { fetchServiceMethodTree } from '@/services/grpctest';
import { grpcAddrList } from '@/services/app';

interface ModalCreatePipelineProps {
  visible: boolean;
  onFinish: (fields: Store) => void;
  onCancel: () => void;
  env: string;
  zoneCode: string;
  appName: string;
}

interface GrpcAddr {
  port: string;
  hosts: {
    env: string;
    addr: string;
  }[];
}

const formItemLayout = {
  labelCol: {
    xs: { span: 24 },
    sm: { span: 4 },
  },
  wrapperCol: {
    xs: { span: 24 },
    sm: { span: 20 },
  },
};
const formItemLayoutWithOutLabel = {
  wrapperCol: {
    xs: { span: 24, offset: 0 },
    sm: { span: 20, offset: 4 },
  },
};

export default function ModalCreatePipeline(props: ModalCreatePipelineProps) {
  const { visible, env, zoneCode, appName } = props;
  const [form] = Form.useForm();
  const [workerZones, setWorkerZones] = useState<WorkerZone[]>([]);
  const [httpCollections, setHttpCollections] = useState<
    { id: number; name: string; test_cases: any[] }[]
  >([]);
  const [grpcTestFlag, setGrpcTestFlag] = useState(false);
  const [services, setServices] = useState([]);
  const [testCases, setTestCases] = useState({}); // service -> test cases
  const [grpcAddr, setGrpcAddr] = useState<GrpcAddr | null>(null);

  useEffect(() => {
    if (visible) {
      grpcAddrList({ app_name: appName }).then((r) => {
        setGrpcAddr(r.data);
      });

      fetchServiceMethodTree(appName).then((r) => {
        if (r.code === 14000) return;
        if (r.code !== 0) {
          message.error(r.msg);
          return;
        }

        setServices(r.data);
      });
    }
  }, [visible]);

  useEffect(() => {
    fetchWorkerZones().then((r) => {
      if (r.code === 14000) return;
      if (r.code !== 0) {
        message.error('加载 Worker 节点失败 ' + r.msg);
        return;
      }

      setWorkerZones(r.data);
    });
  }, []);

  useEffect(() => {
    form.setFieldsValue({
      env: env,
      zone_code: zoneCode === 'all' ? null : zoneCode,
      app_name: appName,
      unit_test: true,
      code_check: true,
    });

    fetchCollections(appName).then((r) => {
      if (r.code === 14000) return;
      if (r.code !== 0) {
        message.error(r.msg);
        return;
      }

      setHttpCollections(r.data.list || []);
    });
  }, [env, zoneCode, appName]);

  const testCaseCascadeOptions =
    services?.map((item: any, index: number) => {
      return {
        value: item.id,
        label: item.name,
        children: item.methods?.map((method: any) => ({
          value: method.id,
          label: method.name,
          children:
            method.use_cases?.map((useCase: any) => ({
              value: useCase.id,
              label: useCase.name,
            })) || [],
        })),
      };
    }) || [];

  return (
    <Modal
      title={'创建 Pipeline'}
      visible={visible}
      onOk={() => form.submit()}
      onCancel={props.onCancel}
      width={grpcTestFlag ? '900px' : '500px'}
    >
      <Form form={form} onFinish={props.onFinish}>
        <Row gutter={15}>
          <Col span={grpcTestFlag ? 10 : 24}>
            <Form.Item label={'Env'} name={'env'}>
              <Input disabled />
            </Form.Item>

            <Form.Item label={'App'} name={'app_name'}>
              <Input disabled />
            </Form.Item>

            <Form.Item
              label={'名称'}
              name={'name'}
              rules={[
                { required: true, message: '请输入 Pipeline 名称' },
                {
                  pattern: /^[a-zA-Z0-9_-]{4,32}$/,
                  message: 'Pipeline名称只能为 a-zA-Z0-9_- 组合，长度为 4 - 32 位',
                },
              ]}
            >
              <Input />
            </Form.Item>

            <Form.Item
              label={'代码分支'}
              name={'branch'}
              rules={[{ required: true, message: '请输入代码分支' }]}
            >
              <Input />
            </Form.Item>

            <Form.Item
              label={'机房'}
              name={'zone_code'}
              rules={[{ required: true, message: '请选择机房' }]}
            >
              <Select disabled={zoneCode !== 'all'}>
                {workerZones.map((item, id) => (
                  <Select.Option key={id} value={item.zone_code}>
                    {item.zone_name}
                  </Select.Option>
                ))}
              </Select>
            </Form.Item>

            <Form.Item label={'Http测试集合(可选)'} name={'http_test_collection'}>
              <Select allowClear>
                {httpCollections.map((item, idx) => (
                  <Select.Option value={item.id} key={idx}>
                    {item.name}({item.test_cases.length}个用例)
                  </Select.Option>
                ))}
              </Select>
            </Form.Item>

            <Form.Item label={'单元测试'} name={'unit_test'} valuePropName={'checked'}>
              <Switch />
            </Form.Item>

            <Form.Item label={'静态检查'} name={'code_check'} valuePropName={'checked'}>
              <Switch />
            </Form.Item>

            <Form.Item label={'GRPC接口测试'}>
              <Switch
                onChange={(val) => {
                  setGrpcTestFlag(val);
                  form.setFieldsValue({
                    grpc_test_cases: val ? [{}] : [],
                  });
                }}
              />
            </Form.Item>
          </Col>

          {/*GRPC 测试用例*/}
          {grpcTestFlag && (
            <Col span={14}>
              <Form.Item label={'GRPC服务地址'} name={'grpc_test_addr'}>
                <AutoComplete placeholder={'1.2.3.4:1234'}>
                  {grpcAddr &&
                    grpcAddr.hosts?.map((item, idx) => (
                      <AutoComplete.Option value={item.addr + ':' + grpcAddr.port}>
                        <Tag>{item.env}</Tag> {item.addr} : {grpcAddr.port}
                      </AutoComplete.Option>
                    ))}
                </AutoComplete>
              </Form.Item>
              <Form.List name={'grpc_test_cases'}>
                {(fields, { add, remove }) => {
                  return (
                    <div>
                      {fields.map((field, index) => {
                        return (
                          <Form.Item
                            {...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
                            label={index === 0 ? 'GRPC用例' : ''}
                            key={field.key}
                          >
                            <Space>
                              <Form.Item
                                noStyle
                                name={[field.name, 'testcase']}
                                rules={[{ required: true, message: '请选择用例' }]}
                              >
                                <Cascader
                                  options={testCaseCascadeOptions}
                                  style={{ width: '400px' }}
                                />
                              </Form.Item>

                              <Form.Item noStyle>
                                {index > 0 && (
                                  <MinusCircleOutlined
                                    onClick={() => {
                                      setTestCases({
                                        ...testCases,
                                        [field.name]: undefined,
                                      });
                                      remove(field.name);
                                    }}
                                  />
                                )}
                              </Form.Item>
                            </Space>
                          </Form.Item>
                        );
                      })}

                      <Form.Item>
                        <Button
                          type="dashed"
                          onClick={() => {
                            add();
                          }}
                          block
                        >
                          <PlusOutlined /> 新增用例
                        </Button>
                      </Form.Item>
                    </div>
                  );
                }}
              </Form.List>
            </Col>
          )}
        </Row>
      </Form>
    </Modal>
  );
}
